package net.ankao.job.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import net.ankao.framework.starter.base.utils.CommonUtil;
import net.ankao.job.common.ClientRouterManager;
import net.ankao.job.common.HeartbeatNamingManager;
import net.ankao.job.common.JobNamingManager;
import net.ankao.job.core.common.JobConfig;
import net.ankao.job.entity.AkApplication;
import net.ankao.job.entity.AkApplicationClient;
import net.ankao.job.entity.AkApplicationJob;
import net.ankao.job.entity.dto.ApplicationClientListDTO;
import net.ankao.job.mapper.AkApplicationClientMapper;
import net.ankao.job.service.IAkApplicationClientService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 应用客户端 服务实现类
 * </p>
 *
 * @author LILU
 * @since 2024-11-15
 */
@Service
public class AkApplicationClientServiceImpl extends ServiceImpl<AkApplicationClientMapper, AkApplicationClient> implements IAkApplicationClientService {

    @Resource
    private HeartbeatNamingManager heartbeatNamingManager;

    @Resource
    private JobNamingManager jobNamingManager;


    @Override
    public void onLine(JobConfig jobConfig, AkApplication akApplication) {
        AkApplicationClient akApplicationClient = new AkApplicationClient();
        akApplicationClient.setId(CommonUtil.generateUUID());
        akApplicationClient.setApplicationId(akApplication.getId());
        akApplicationClient.setApplicationName(jobConfig.getApplicationName());
        akApplicationClient.setClientUrl(jobConfig.getClientIp());
        akApplicationClient.setClientPort(jobConfig.getClientPort());
        akApplicationClient.setJoinTime(LocalDateTime.now());
        akApplicationClient.setLastHeartbeatTime(LocalDateTime.now());
        akApplicationClient.setNamespaceId(akApplication.getNamespaceId());
        akApplicationClient.setStatus(1);
        try {
            this.baseMapper.insert(akApplicationClient);
            heartbeatNamingManager.addNaming(akApplicationClient);
        }catch (DuplicateKeyException e){
            LambdaQueryWrapper<AkApplicationClient> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(AkApplicationClient::getApplicationId,akApplicationClient.getApplicationId());
            lambdaQueryWrapper.eq(AkApplicationClient::getClientUrl,akApplicationClient.getClientUrl());
            lambdaQueryWrapper.eq(AkApplicationClient::getClientPort,akApplicationClient.getClientPort());
            AkApplicationClient old = this.baseMapper.selectOne(lambdaQueryWrapper);
            old.setLastHeartbeatTime(LocalDateTime.now());
            old.setStatus(1);
            this.baseMapper.updateById(old);
            heartbeatNamingManager.addNaming(old);
        }
    }

    @Override
    public void downUp(String id) {
        LambdaUpdateWrapper<AkApplicationClient> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(AkApplicationClient::getId,id);
        lambdaUpdateWrapper.set(AkApplicationClient::getStatus,0);
        this.baseMapper.update(null,lambdaUpdateWrapper);
        heartbeatNamingManager.delNaming(id);
//        jobNamingManager.delNaming(id);
    }

    @Override
    public void heartbeat(String id) {
        LambdaUpdateWrapper<AkApplicationClient> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(AkApplicationClient::getId,id);
        lambdaUpdateWrapper.set(AkApplicationClient::getLastHeartbeatTime,LocalDateTime.now());
        lambdaUpdateWrapper.set(AkApplicationClient::getStatus,1);
        this.baseMapper.update(null,lambdaUpdateWrapper);
    }

    @Override
    public List<AkApplicationClient> getByExecutiveStrategy(AkApplicationJob applicationJob) {
        LambdaQueryWrapper<AkApplicationClient> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AkApplicationClient::getApplicationId,applicationJob.getApplicationId());
        queryWrapper.eq(AkApplicationClient::getStatus,1);
        queryWrapper.orderByAsc(AkApplicationClient::getJoinTime);
        List<AkApplicationClient> akApplicationClients = this.baseMapper.selectList(queryWrapper);
        List<AkApplicationClient> client = ClientRouterManager.getClient(applicationJob.getExecutiveStrategy(), akApplicationClients);
        return client;
    }

    @Override
    public List<AkApplicationClient> list(ApplicationClientListDTO applicationClientListDTO) {
        LambdaQueryWrapper<AkApplicationClient> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AkApplicationClient::getApplicationId,applicationClientListDTO.getApplicationId());
        queryWrapper.eq(AkApplicationClient::getStatus,1);
        queryWrapper.orderByDesc(AkApplicationClient::getStatus).orderByAsc(AkApplicationClient::getJoinTime);
        List<AkApplicationClient> akApplicationClients = this.baseMapper.selectList(queryWrapper);
        return akApplicationClients;
    }

    @Override
    public Integer delByApplicationId(String applicationId) {
        LambdaQueryWrapper<AkApplicationClient> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AkApplicationClient::getApplicationId,applicationId);
        int i = this.baseMapper.delete(lambdaQueryWrapper);
        return i;
    }
}
